﻿using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace GXYEFCoreDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }

    public class RecipeContext(DbContextOptions options) : DbContext(options)
    {
        public DbSet<Recipe> Recipes { get; set; }
    }

    public class RecipeRepo(SqlConfig config)
    {
        readonly ILogger Logger = Log.ForContext<RecipeRepo>();

        readonly PooledDbContextFactory<RecipeContext> factory = new(new DbContextOptionsBuilder<RecipeContext>()
            .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
            //        .LogTo(Logger.Debug)
            //#if DEBUG
            //        .EnableSensitiveDataLogging()
            //#endif
            .UseSqlite(config.ConnectionString).Options);

        public RecipeContext NewContext()
        {
            return factory.CreateDbContext();
        }

        public async Task<List<ProductRecipe>> GetRecipesByProductId(int productId)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);

            return await ctx.Recipes
                .Include(r => r.Owner)
                .Include(r => r.WaferMap)
                .Where(r => r.ProductId == productId)
                .Select(r => new ProductRecipe
                {
                    Id = r.Id,
                    Name = r.Name,
                    OwnerName = r.Owner.Name,
                    WaferMapId = r.WaferMapId,
                    WaferMapName = r.WaferMap.Name,
                    LastUpdated = r.LastUpdated,
                    Created = r.Created,
                    Description = r.Description,
                })
                .ToListAsync().ConfigureAwait(false);
        }

        public async Task Create(Recipe recipe)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            ctx.Add(recipe);
            await ctx.SaveChangesAsync().ConfigureAwait(false);
        }

        public async Task UpdateRecipeSEMConditionIdById(
        List<int> ids,
        int no,
        JobEnvironment env)
        {
            if (ids == null || !ids.Any()) return;

            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);

            await ctx.Recipes
                .Where(p => ids.Contains(p.Id)) // 使用Contains生成SQL IN语句
                .ExecuteUpdateAsync(update => update
                    .SetProperty(p => p.SEMConditionNo, no)
                    .SetProperty(p => p.Environment.MatchFailureMode, env.MatchFailureMode)
                    .SetProperty(p => p.Environment.RequireConfirmation, env.RequireConfirmation)
                    .SetProperty(p => p.Environment.IsDYNEnabled, env.IsDYNEnabled)
                    .SetProperty(p => p.Environment.ManualAssistAlignment, env.ManualAssistAlignment)
                    .SetProperty(p => p.Environment.ManualAssistAddressing, env.ManualAssistAddressing)
                    .SetProperty(p => p.Environment.ManualAssistMeasurement, env.ManualAssistMeasurement))
                .ConfigureAwait(false);
        }

        public async Task UpdateRecipeSEMConditionIdById(int id, int no, JobEnvironment env)
        {
            await UpdateRecipeSEMConditionIdById(new List<int> { id }, no, env);
        }

        public async Task UpdateNameById(int id, string name)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            await ctx.Recipes
                .Where(r => r.Id == id)
                .ExecuteUpdateAsync(setters => setters.SetProperty(r => r.Name, name));
        }

        public async Task<Recipe> GetById(int id)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            return await ctx.Recipes
                .Where(r => r.Id == id)
                .FirstAsync().ConfigureAwait(false);
        }
        public async Task<List<Recipe>> GetAllRecipe()
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            return await ctx.Recipes
                .ToListAsync().ConfigureAwait(false);
        }

        public async Task DeleteById(int id)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            await ctx.Recipes.Where(p => p.Id == id).ExecuteDeleteAsync().ConfigureAwait(false);
        }

        public async Task UpdateJsonById(int id, string json)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            await ctx.Recipes
                .Where(p => p.Id == id)
                .ExecuteUpdateAsync(update => update.SetProperty(p => p.PatternJson, json)).ConfigureAwait(false);
        }

        public async Task<int?> GetMaxRecipeId()
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            return await ctx.Recipes.MaxAsync(r => (int?)r.Id).ConfigureAwait(false);
        }

        public async Task UpdateRecipeEnvAndPatternById(int id, string patternJson, JobEnvironment env)
        {
            using var ctx = await factory.CreateDbContextAsync().ConfigureAwait(false);
            await ctx.Recipes
                .Where(p => p.Id == id)
                .ExecuteUpdateAsync(update => update
                    .SetProperty(p => p.PatternJson, patternJson)
                    .SetProperty(p => p.Environment.MatchFailureMode, env.MatchFailureMode)
                    .SetProperty(p => p.Environment.RequireConfirmation, env.RequireConfirmation)
                    .SetProperty(p => p.Environment.IsDYNEnabled, env.IsDYNEnabled));
        }
    }

}
